package com.atguigu.gmall.item.service.impl;

import com.atguigu.core.bean.Resp;
import com.atguigu.gmall.item.feign.GmallPmsFeign;
import com.atguigu.gmall.item.feign.GmallSmsFeign;
import com.atguigu.gmall.item.feign.GmallWmsFeign;
import com.atguigu.gmall.item.service.ItemService;
import com.atguigu.gmall.item.vo.ItemVO;
import com.atguigu.gmall.pms.entity.SkuImagesEntity;
import com.atguigu.gmall.pms.entity.SkuInfoEntity;
import com.atguigu.gmall.pms.entity.SkuSaleAttrValueEntity;
import com.atguigu.gmall.pms.entity.SpuInfoDescEntity;
import com.atguigu.gmall.pms.vo.BaseGroupVO;
import com.atguigu.gmall.sms.vo.SaleVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private GmallPmsFeign gmallPmsFeign;
    @Autowired
    private GmallWmsFeign gmallWmsFeign;
    @Autowired
    private GmallSmsFeign gmallSmsFeign;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;


    @Override
    public ItemVO loadItem(Long skuId) throws ExecutionException, InterruptedException {
        ItemVO itemVO = new ItemVO();

        // 1.获取sku的基本信息
        // 后续获取sku的促销信息、spu的销售属性和spu详情信息（需要sku中的spuId）都需要skuInfoEntity
        // supplyAsync有返回值
        // runAsync无返回值
        // 所以这里需要使用supplyAsync
        CompletableFuture<Object> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            Resp<SkuInfoEntity> skuInfoEntityResp = gmallPmsFeign.querySkuById(skuId);
            SkuInfoEntity skuInfoEntity = skuInfoEntityResp.getData();
            if (skuInfoEntity == null) {
                return itemVO;
            }
            BeanUtils.copyProperties(skuInfoEntity, itemVO);
            return skuInfoEntity;
        }, threadPoolExecutor);


        // 2 .获取sku的图片信息
        //不需要上一个任务的结果，也不需要提供返回值
        CompletableFuture<Void> skuImagesListFuture = CompletableFuture.runAsync(() -> {
            Resp<List<SkuImagesEntity>> imagesBySkuId = gmallPmsFeign.queryImagesBySkuId(skuId);
            List<SkuImagesEntity> imagesEntityList = imagesBySkuId.getData();
            List<String> stringList =
                    imagesEntityList.stream().map(SkuImagesEntity::getImgUrl).collect(Collectors.toList());
            itemVO.setPics(stringList);
        }, threadPoolExecutor);


        // 3. 获取sku的促销信息
        CompletableFuture<Void> skuSalesFuture = CompletableFuture.runAsync(() -> {
            Resp<List<SaleVO>> querySalesBySkuIdResp = gmallSmsFeign.querySalesBySkuId(skuId);
            List<SaleVO> saleVOList = querySalesBySkuIdResp.getData();
            itemVO.setSales(saleVOList);
        }, threadPoolExecutor);


        // 4. 获取spu下所有sku的销售属性
        //需要任务1的返回结果
        // thenAcceptAsync：有参数，无返回
        // thenApplyAsync: 有参数，有返回
        CompletableFuture<Void> skuSaleAttrFuture = skuInfoFuture.thenAcceptAsync(skuInfo -> {
            Resp<List<SkuSaleAttrValueEntity>> skuSaleAttrValueBySpuId =
                    gmallPmsFeign.querySkuSaleAttrValueBySpuId(((SkuInfoEntity) skuInfo).getSpuId());
            List<SkuSaleAttrValueEntity> skuSaleAttrValueEntityList = skuSaleAttrValueBySpuId.getData();
            itemVO.setSaleAttrs(skuSaleAttrValueEntityList);
        }, threadPoolExecutor);


        // 5 .获取规格参数及组下的规格参数
        //需要任务1的返回结果
        CompletableFuture<Void> baseGroupFuture = skuInfoFuture.thenAcceptAsync(skuInfo -> {
            Resp<List<BaseGroupVO>> itemGroupVoResp =
                    gmallPmsFeign.queryItemGroupVoByCidAndSpuId(((SkuInfoEntity) skuInfo).getCatalogId(), ((SkuInfoEntity) skuInfo).getSpuId());
            List<BaseGroupVO> baseGroupVOList = itemGroupVoResp.getData();
            itemVO.setAttrGroups(baseGroupVOList);
        }, threadPoolExecutor);


        // 6.spu详情介绍
        //需要任务1的返回结果
        CompletableFuture<Void> spuInfoDescFuture = skuInfoFuture.thenAcceptAsync(skuInfo -> {
            Resp<SpuInfoDescEntity> spuInfoDescEntityResp = gmallPmsFeign.querySpuInfoDescById(((SkuInfoEntity) skuInfo).getSpuId());
            SpuInfoDescEntity spuInfoDescEntity = spuInfoDescEntityResp.getData();
            itemVO.setDesc(spuInfoDescEntity);
        }, threadPoolExecutor);

        //需要全部任务执行完后，主线程才能执行返回操作
        //任务1不需要加进来，因为任务4、5、6都需要任务1的返回结果，所以指定任务2，3，4，5，6就行
        CompletableFuture<Void> allFuture = CompletableFuture.allOf(skuImagesListFuture, skuSalesFuture, skuSaleAttrFuture, baseGroupFuture, spuInfoDescFuture);

        // 阻塞主进程，等待子进程全部执行完毕！
        allFuture.get();

        return itemVO;
    }
}
